
#include <iostream>
#include <string>
#include <list>
using namespace std;

#include <boost/intrusive_ptr.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/cast.hpp>

class ref_count {
public:
	ref_count () : m_count(0) {}
	virtual ~ref_count() {}
	inline
	void add_ref () {
		++m_count;
	}
	inline
	bool release () {
		return 0 == (--m_count);
	}

	virtual
	void destroy_deallocate () = 0;

private:
	int m_count;
};
inline
void intrusive_ptr_add_ref (ref_count *p_counter) {
	p_counter->add_ref();
}

inline
void intrusive_ptr_release (ref_count *p_counter) {
	if (p_counter->release())
		p_counter->destroy_deallocate();
}

/*
template <typename T>
void destroy_dealloc (T *p, typename T::allocator p_alloc=typename T::allocator()) {
	cout << typeid(T).name() << " destroy_dealloc" << endl;
	p_alloc.destroy(p);
	p_alloc.deallocate(p);
}

template <typename T>
T *alloc_construct (const T &val, typename T::allocator p_alloc=typename T::allocator()) {
	cout << typeid(T).name() << " alloc_construct" << endl;
	T *p = p_alloc.allocate();
	p_alloc.construct(p, val);
	return p;
}

template<typename T>
inline
void intrusive_ptr_add_ref (T *p_counter, typename T::allocator p_alloc=typename T::allocator()) {
	p_counter->add_ref();
}

template<typename T>
inline
void intrusive_ptr_release (T *p_counter, typename T::allocator p_alloc=typename T::allocator()) {
	if (p_counter->release())
		destroy_dealloc(p_counter, p_alloc);
}
*/

class kv_list : public ref_count {
public:
	typedef boost::fast_pool_allocator<kv_list> allocator;
	typedef boost::intrusive_ptr<kv_list> pointer;

	virtual
	void destroy_deallocate () {
		cout << "kv_list::destroy_deallocate" << endl;
		m_allocator.destroy(this);
		m_allocator.deallocate(this);
	}

public:
	kv_list () {
		cout << "kv_list()" << endl;
	}
	kv_list (const kv_list &rhs) {
		cout << "kv_list(const kv_list&)" << endl;
	}
	virtual ~kv_list () {
		cout << "~kv_list()" << endl;
	}

	virtual void * get_scanner () {
		return NULL;
	}
private:
	allocator m_allocator;
};

class table : public kv_list {
public:
	typedef boost::fast_pool_allocator<table> allocator;
	typedef boost::intrusive_ptr<table> pointer;

	virtual
	void destroy_deallocate () {
		cout << "table::destroy_deallocate" << endl;
		m_allocator.destroy(this);
		m_allocator.deallocate(this);
	}

	void *operator new (size_t, const char *prefix, table *p, const char *append) {
		cout << prefix << append << endl;
		return p;
	}
	void *operator new (size_t, table *p) {
		return p;
	}
public:
	table () {
		cout << "table()" << endl << flush;
	}
	table (const table &rhs) {
		cout << "table(const table&)" << endl;
	}
	~table () {
		cout << "~table()" << endl;
	}

private:
	allocator m_allocator;
};

int main () try{
	const int count = 3;
	table _table;
	{
		cout << "section 1" << endl;
		
		list<table::pointer> tables;
		
		table::allocator _alloc;
		for (int i=0; i<count; ++i) {
			table *ptr(_alloc.allocate());
			cout << "construct " << i << endl;
			_alloc.construct(ptr, _table);
			tables.push_back(ptr);
		}
	}
	{
		cout << "section 2" << endl;
		
		list<kv_list::pointer> lists;

		for (int i=0; i<count; ++i) {
			kv_list *ptr;
			if (i%2) {
				ptr = kv_list::allocator::allocate();
				kv_list::allocator _alloc;
				_alloc.construct(ptr, _table);
			} else {
				ptr = table::allocator::allocate();
				table::allocator _alloc;
				_alloc.construct(static_cast<table*>(ptr), _table);
			}
			lists.push_back(ptr);
		}
	}
	{
		cout << "section 3" << endl;
		
		list<table::pointer, table::allocator::rebind<table::pointer>::other> tables;
		table::allocator _alloc;
		for (int i=0; i<count; ++i) {
			table *ptr (_alloc.allocate());
			//_alloc.construct(ptr, _table);
			new("this is prefix", ptr,"this is append") table();
			tables.push_back(ptr);
		}
	}

	return 0;
} catch (...) {
	return 0;
}

